/*
 * Copyright (c) 2016 EEFUNG Software Co.Ltd. All rights reserved.
 * 版权所有(c)2016湖南蚁坊软件有限公司。保留所有权利。
 */

package com.zidian.leader.common.util;

import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.support.annotation.RequiresApi;
import android.text.format.Formatter;

import com.orhanobut.logger.Logger;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Date;

import static android.app.ActivityManager.MemoryInfo;

/**
 * 错误信息生成器
 * Created by Zuo Ji on 2015/10/13.
 */
public class ErrorLogBuilder {

    // 报错时间
    private static final String LOG_DATE = "LOG_DATE";
    // 用户手动输入的错误描述
    private static final String USER_COMMENT = "USER_COMMENT";
    // 系统版本信息
    private static final String ANDROID_VERSION = "ANDROID_VERSION";
    // 手机品牌
    private static final String PHONE_BRAND = "PHONE_BRAND";
    // 手机型号
    private static final String PHONE_MODEL = "PHONE_MODEL";
    // 手机分辨率
    private static final String PHONE_DISPLAY = "PHONE_DISPLAY";
    // 网络状态
    private static final String NETWORK_STATE = "NETWORK_STATE";
    // 内存大小
    private static final String PHONE_TOTAL_STORAGE = "PHONE_TOTAL_STORAGE";
    // 可用内存大小
    private static final String PHONE_AVAILABLE_STORAGE = "PHONE_AVAILABLE_STORAGE";
    // 运行内存大小
    private static final String RUNNING_MEMORY = "RUNNING_MEMORY";
    // App 版本名称
    private static final String APP_VERSION_NAME = "APP_VERSION_NAME";
    // App 版本号
    private static final String APP_VERSION_CODE = "APP_VERSION_CODE";
    // App 包名
    private static final String APP_PACKAGE_NAME = "APP_PACKAGE_NAME";
    // App 登录的账号
    private static final String APP_USER_NAME = "APP_USER_NAME";
    // 报错的堆栈信息
    private static final String APP_STACK_TRACE = "APP_STACK_TRACE";

    // 等号
    private static final String EQUAL = " = ";
    // 换行符号
    private static final String WRAP = "\r\n";


    /**
     * 生成错误信息
     * @param context 上下文
     * @param userComment 用户手动输入的错误描述信息
     * @param networkState 报错时的网络状态
     * @param throwable 报错的异常
     * @return  错误信息
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    public static String buildErrorLog(Context context, String userComment,
                                       String networkState, Throwable throwable) {
        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.append(LOG_DATE);
        stringBuilder.append(EQUAL);
        stringBuilder.append(DatetimeUtils.format(new Date(System.currentTimeMillis())));
        stringBuilder.append(WRAP);

        if (StringUtils.hasText(userComment)) {
            stringBuilder.append(USER_COMMENT);
            stringBuilder.append(EQUAL);
            stringBuilder.append(userComment);
            stringBuilder.append(WRAP);
        }

        String androidVersion = Build.VERSION.RELEASE;
        if (StringUtils.hasText(androidVersion)) {
            stringBuilder.append(ANDROID_VERSION);
            stringBuilder.append(EQUAL);
            stringBuilder.append(androidVersion);
            stringBuilder.append(WRAP);
        }

        String brand = Build.BRAND;
        if (StringUtils.hasText(brand)) {
            stringBuilder.append(PHONE_BRAND);
            stringBuilder.append(EQUAL);
            stringBuilder.append(brand);
            stringBuilder.append(WRAP);
        }

        String model = Build.MODEL;
        if (StringUtils.hasText(model)) {
            stringBuilder.append(PHONE_MODEL);
            stringBuilder.append(EQUAL);
            stringBuilder.append(model);
            stringBuilder.append(WRAP);
        }

        String display = DensityUtils.getDisplayInfo(context);
        if (StringUtils.hasText(display)) {
            stringBuilder.append(PHONE_DISPLAY);
            stringBuilder.append(EQUAL);
            stringBuilder.append(display);
            stringBuilder.append(WRAP);
        }

        if (StringUtils.hasText(networkState)) {
            stringBuilder.append(NETWORK_STATE);
            stringBuilder.append(EQUAL);
            stringBuilder.append(networkState);
            stringBuilder.append(WRAP);
        }

        String phoneTotalMemStr = getPhoneTotalMemorySize(context);
        if (StringUtils.hasText(phoneTotalMemStr)) {
            stringBuilder.append(PHONE_TOTAL_STORAGE);
            stringBuilder.append(EQUAL);
            stringBuilder.append(phoneTotalMemStr);
            stringBuilder.append(WRAP);
        }

        String phoneAvailableMemStr = getPhoneAvailableMemorySize(context);
        if (StringUtils.hasText(phoneAvailableMemStr)) {
            stringBuilder.append(PHONE_AVAILABLE_STORAGE);
            stringBuilder.append(EQUAL);
            stringBuilder.append(phoneAvailableMemStr);
            stringBuilder.append(WRAP);
        }

        String runningMemSizeStr = getRunningMemorySize(context);
        if (StringUtils.hasText(runningMemSizeStr)) {
            stringBuilder.append(RUNNING_MEMORY);
            stringBuilder.append(EQUAL);
            stringBuilder.append(runningMemSizeStr);
            stringBuilder.append(WRAP);
        }

        PackageInfo packageInfo = null;
        try {
            packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
        }
        catch(PackageManager.NameNotFoundException ex) {
            Logger.e(ex.toString());
        }
        if (packageInfo != null) {
            if (StringUtils.hasText(packageInfo.versionName)) {
                stringBuilder.append(APP_VERSION_NAME);
                stringBuilder.append(EQUAL);
                stringBuilder.append(packageInfo.versionName);
                stringBuilder.append(WRAP);
            }

            if (packageInfo.versionCode != 0) {
                stringBuilder.append(APP_VERSION_CODE);
                stringBuilder.append(EQUAL);
                stringBuilder.append(packageInfo.versionCode);
                stringBuilder.append(WRAP);
            }

            if (StringUtils.hasText(packageInfo.packageName)) {
                stringBuilder.append(APP_PACKAGE_NAME);
                stringBuilder.append(EQUAL);
                stringBuilder.append(packageInfo.packageName);
                stringBuilder.append(WRAP);
            }
        }

        stringBuilder.append(APP_USER_NAME);
        stringBuilder.append(EQUAL);
        stringBuilder.append(HawkUtils.getUsername());
        stringBuilder.append(WRAP);

        String stackTrace = getStackTrace(throwable);
        if (StringUtils.hasText(stackTrace)) {
            stringBuilder.append(APP_STACK_TRACE);
            stringBuilder.append(EQUAL);
            stringBuilder.append(stackTrace);
            stringBuilder.append(WRAP);
        }

        return stringBuilder.toString();
    }


    /**
     * 获取报错时的堆栈信息
     * @param th 错误信息
     * @return 报错时的堆栈信息
     */
    private static String getStackTrace(Throwable th) {

        final Writer result = new StringWriter();
        final PrintWriter printWriter = new PrintWriter(result);

        Throwable cause = th;
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        final String stacktraceAsString = result.toString();
        printWriter.close();

        return stacktraceAsString;
    }

    /**
     * 获取机身可用内存
     * @return 返回机身可用内存大小
     */
    private static String getPhoneAvailableMemorySize(Context context) {
        final File path = Environment.getDataDirectory();
        final StatFs stat = new StatFs(path.getPath());
        final long blockSize = stat.getBlockSize();
        final long availableBlocks = stat.getAvailableBlocks();
        long size = availableBlocks * blockSize;
        return Formatter.formatFileSize(context, size);
    }

    /**
     * 获取机身总内存
     * @return 返回机身总内存大小
     */
    private static String getPhoneTotalMemorySize(Context context) {
        final File path = Environment.getDataDirectory();
        final StatFs stat = new StatFs(path.getPath());
        final long blockSize = stat.getBlockSize();
        final long totalBlocks = stat.getBlockCount();
        long size = totalBlocks * blockSize;
        return Formatter.formatFileSize(context, size);
    }

    /**
     * 获取系统的运行内存
     * @param context 上下文
     * @return 运行内存
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    private static String getRunningMemorySize(Context context){
        //获得MemoryInfo对象
        MemoryInfo memoryInfo = new MemoryInfo() ;
        //获得系统可用内存，保存在MemoryInfo对象上
        ActivityManager mActivityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        mActivityManager.getMemoryInfo(memoryInfo) ;
        long memSize = memoryInfo.totalMem ;

        return Formatter.formatFileSize(context, memSize);
    }
}